package cn.buk.tms.eotms.response;

import cn.buk.common.flight.dto.FlightInfoDto;
import cn.buk.common.util.DateUtil;
import cn.buk.tms.api.flight.ApiPriceDto;
import cn.buk.tms.common.dto.base.BaseOrderDto;
import cn.buk.tms.common.dto.flight.BaseFlightOrderPassengerDto;
import cn.buk.tms.eotms.dto.CarOrderDto;
import cn.buk.tms.eotms.entity.*;
import cn.buk.tms.eotms.util.OrderUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.springframework.beans.BeanUtils;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static cn.buk.tms.common.constant.TmsOrderConstant.*;

/**
 * @author yfdai
 */
@JsonPropertyOrder({"id", "orderNo", "psgCount", "segCount", "subTotal", "totalAmount"})
public class FlightOrderResponseDto extends BaseOrderDto {

  private List<ApiPriceDto> prices;


  /**
   * 接口参数: 联系人
   */
  private String linkman;

  /**
   * 联系电话
   */
  private String linkPhone;

  /**
   * 是否国际/港澳台票
   * 0-否
   * 1-是
   */
  private int intlTicket;


  /**
   * 是否需要发票或行程单
   * 0-不需要
   * 1-行程单
   * 2-发票
   * 3-信息单
   * 4-行程单 + 捆绑产品（比如30元航意险/人/航段）
   */
  private int itineraryType;

  /**
   * 接口参数
   * 邮寄地址
   */
  private String address;

  /**
   * 接口参数
   * 备注
   */
  private String remark;

  /**
   * 接口参数
   * 政策代码：机票私有政策，大客户政策的代码
   */
  private String policyCode;


  /**
   * 接口参数
   * 总收客金额(成人+儿童+婴儿）
   */
  private double totalAmount;

  //订单生成接口请求参数 截止


  /**
   * 创建此账单的用户名
   */
  private String operator;


  /**
   * 记录编号：前台有部分客户是需要可以看到的
   */
  private String pnrNo;
  /**
   * 记录编号内容
   */
  private String pnrDetail;


  /**
   * 客户付款备注：用来选择具体哪一种付款方式
   */
  private String payRemark;

  /**
   * 行程类型
   * 1-单程
   * 2－来回
   * 3－多程
   */
  private int routeType;

  /**
   * 如果是总订单，则用subTotal保存机票订单的总价
   */
  private Double subTotal;

  /**
   * 订单创建日期
   */
  @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
  private Date createDate;
  /**
   * 订单金额是否已校验
   * 0 - 未校验
   * 1 - 校验通过
   * 4 - 校验失败, 需要人工干预
   */
  private int priceCheckedStatus;
  /**
   * 订单金额校验时间
   */
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
  private Date priceCheckedTime;
  /**
   * 如果该订单需要审批，则系统在此设置指定审批人
   */
  private String specifiedApprover;
  /**
   * 审批状态：
   * null - 未处理
   * 1 - 同意
   * 0 - 不同意
   */
  private Integer approvalStatus;
  /**
   * 审批如果拒绝，拒绝的原因描述
   */
  private String approvalDenyReason;
  /**
   * 是否违反差旅政策
   * null - 未处理
   * 0 - 未违反
   * 1 - 违反
   */
  private Integer violationStatus;
  /**
   * 违反差旅政策的原因描述
   */
  private String violationReason;

  /**
   * 出票时限
   */
  @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
  private Date tktlDate;

  /**
   * 出票日期
   */
  @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
  private Date etdzDate;

  /**
   * 机票订单的使用状态
   */
  private Integer showStatus;

  /**
   * 航班信息
   */
  private List<FlightInfoDto> flights;

  /**
   * 乘机人信息
   */
  private List<FlightOrderPassengerDto> passengers;

  /**
   * 票号信息
   */
  private List<FlightOrderTicketDto> tickets;

  /**
   * 与订单相关联的退票单
   */
  private List<RefundOrderResponseDto> refunds;

  /**
   * 与订单相关联的改签单
   */
  private List<ChangeOrderResponseDto> changes;

  /**
   * 与订单相关联的服务单
   */
  private List<VasOrderResponseDto> services;
  /**
   * 与订单相关联的租车订单
   */
  private List<CarOrderDto> cars;
  /**
   * 子订单
   */
  private List<BaseOrderDto> subOrders;


  public static FlightOrderResponseDto createByFlightOrder(FlightOrder o) {
    var dto = new FlightOrderResponseDto();

    BeanUtils.copyProperties(o, dto, "flights", "passengers", "tickets");

    //订单状态
    dto.setOrderStatus(o.getStatus());
    //价格校验状态
    dto.setPriceCheckedStatus(o.getPriceChecked() == null ? 0 : o.getPriceChecked());
    //审批相关信息
    OrderUtil.copyApprovalInfo(o.getApprovalInfo(), dto);


    // 成人部分的价格
    if (o.getAdultCount() > 0) {
      var priceDto = new ApiPriceDto();
      dto.getPrices().add(priceDto);
      priceDto.setPriceType(0);
      priceDto.setPrice(o.getPrice());
      priceDto.setParValue(o.getParvalue());
      priceDto.setTax(o.getTax());
      priceDto.setServiceCharge(o.getServiceCharge());
      priceDto.setDiscount(o.getDiscount());
    }

    // 儿童部分的价格
    if (o.getChildCount() > 0) {
      var priceDto = new ApiPriceDto();
      dto.getPrices().add(priceDto);
      priceDto.setPriceType(1);
      priceDto.setPrice(o.getChdPrice());
      priceDto.setParValue(o.getChdParvalue());
      priceDto.setTax(o.getChdTax());
      priceDto.setServiceCharge(o.getChdServiceCharge());
      priceDto.setDiscount(o.getChdDiscount());
    }

    // 婴儿部分的价格
    if (o.getInfantCount() > 0) {
      var priceDto = new ApiPriceDto();
      dto.getPrices().add(priceDto);
      priceDto.setPriceType(2);
      priceDto.setPrice(o.getInfPrice());
      priceDto.setParValue(o.getInfParvalue());
      priceDto.setTax(o.getInfTax());
      priceDto.setServiceCharge(o.getInfServiceCharge());
      priceDto.setDiscount(o.getInfDiscount());
    }

    for (FlightOrderFlight flt : o.getFlights()) {
      FlightOrderFlightDto fltDto = new FlightOrderFlightDto();
      fltDto.setSegOrder(flt.getSegOrder());

      FlightInfo f0 = flt.getFlight();
      BeanUtils.copyProperties(f0, fltDto);
      fltDto.setDportName(f0.getDepartureAirportName());
      fltDto.setAportName(f0.getArrivalAirportName());

      if (flt.getFlight().getDdate().length() > 0) {
        try {
          fltDto.setDdate(DateUtil.convertToDate(flt.getFlight().getDdate(), "yyyy-MM-dd"));
        } catch (ParseException ignored) {

        }
      }
      if (flt.getFlight().getArrivalDate().length() > 0) {
        try {
          fltDto.setAdate(DateUtil.convertToDate(flt.getFlight().getArrivalDate(), "yyyy-MM-dd"));
        } catch (ParseException ignored) {
        }
      }


      fltDto.setChangeRule(flt.getChangeRule());
      fltDto.setRefundRule(flt.getRefundRule());

      dto.getFlights().add(fltDto);
    }

    for (FlightOrderPassenger psg0 : o.getPassengers()) {
      FlightOrderPassengerDto psg1 = new FlightOrderPassengerDto();
      BeanUtils.copyProperties(psg0, psg1);

      dto.getPassengers().add(psg1);
    }

    for (FlightOrderTicket ticket : o.getTickets()) {
      FlightOrderTicketDto ticketDto = new FlightOrderTicketDto();
      dto.getTickets().add(ticketDto);

      BeanUtils.copyProperties(ticket, ticketDto);

      for (FlightOrderPassenger psg : o.getPassengers()) {
        if (psg.getId() == ticket.getPassengerId()) {
          ticketDto.setPassengerName(psg.getName());
          break;
        }
      }
    }

    dto.setSubTotal(dto.getTotalAmount());


    return dto;
  }


  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
  private Date createTime;

  public String getShowStatusDesc() {
    if (this.showStatus == null) {
      return null;
    }
    switch (this.showStatus) {
      case FLIGHT_ORDER_TICKET_WHOLE_USED:
        return "已使用";
      case FLIGHT_ORDER_TICKET_WHOLE_REFUNDED:
        return "已退票";
      case FLIGHT_ORDER_TICKET_WHOLE_EXCHANGED:
        return "已改签";
      case FLIGHT_ORDER_TICKET_PARTIAL_USED
              + FLIGHT_ORDER_TICKET_PARTIAL_EXCHANGED:
        return "部分使用改签";
      case FLIGHT_ORDER_TICKET_PARTIAL_USED
              + FLIGHT_ORDER_TICKET_PARTIAL_REFUNDED:
        return "部分使用退票";
      case FLIGHT_ORDER_TICKET_PARTIAL_EXCHANGED
              + FLIGHT_ORDER_TICKET_PARTIAL_REFUNDED:
        return "部分改签退票";
      case FLIGHT_ORDER_TICKET_PARTIAL_USED
              + FLIGHT_ORDER_TICKET_PARTIAL_EXCHANGED
              + FLIGHT_ORDER_TICKET_PARTIAL_REFUNDED:
        return "部分使用改签退票";
      default:
        return "";
    }
  }


  public List<FlightInfoDto> getFlights() {
    if (flights == null) {
      flights = new ArrayList<>();
    }
    return flights;
  }

  public void setFlights(List<FlightInfoDto> flights) {
    this.flights = flights;
  }

  public List<FlightOrderPassengerDto> getPassengers() {
    if (passengers == null) {
      passengers = new ArrayList<>();
    }
    return passengers;
  }

  public void setPassengers(List<FlightOrderPassengerDto> passengers) {
    this.passengers = passengers;
  }


  public Date getTktlDate() {
    return tktlDate;
  }

  public void setTktlDate(Date tktlDate) {
    this.tktlDate = tktlDate;
  }

  public Date getCreateTime() {
    return createTime;
  }

  public void setCreateTime(Date createTime) {
    this.createTime = createTime;
  }

  public Date getEtdzDate() {
    return etdzDate;
  }

  public void setEtdzDate(Date etdzDate) {
    this.etdzDate = etdzDate;
  }

  public List<RefundOrderResponseDto> getRefunds() {
    if (refunds == null) {
      refunds = new ArrayList<>();
    }
    return refunds;
  }

  public void setRefunds(List<RefundOrderResponseDto> refunds) {
    this.refunds = refunds;
  }

  public List<ChangeOrderResponseDto> getChanges() {
    if (changes == null) {
      changes = new ArrayList<>();
    }
    return changes;
  }

  public void setChanges(List<ChangeOrderResponseDto> changes) {
    this.changes = changes;
  }

  public List<VasOrderResponseDto> getServices() {
    if (services == null) {
      services = new ArrayList<>();
    }
    return services;
  }

  public void setServices(List<VasOrderResponseDto> services) {
    this.services = services;
  }

  public List<BaseOrderDto> getSubOrders() {
    if (subOrders == null) {
      subOrders = new ArrayList<>();
    }
    return subOrders;
  }

  public void setSubOrders(List<BaseOrderDto> subOrders) {
    this.subOrders = subOrders;
  }


  public List<CarOrderDto> getCars() {
    if (cars == null) {
      cars = new ArrayList<>();
    }
    return cars;
  }

  public void setCars(List<CarOrderDto> cars) {
    this.cars = cars;
  }

  public Integer getShowStatus() {
    return showStatus;
  }

  public void setShowStatus(int showStatus) {
    this.showStatus = showStatus;
  }

  public List<FlightOrderTicketDto> getTickets() {
    if (tickets == null) {
      tickets = new ArrayList<>();
    }
    return tickets;
  }

  public void setTickets(List<FlightOrderTicketDto> tickets) {
    this.tickets = tickets;
  }

  public void processPassengerTicketStatus() {
    for (BaseFlightOrderPassengerDto psg : this.getPassengers()) {
      int ticketStatus = -1;
      for (FlightOrderTicketDto ticket : this.getTickets()) {
        if (!ticket.getPassengerName().equalsIgnoreCase(psg.getName())) {
          continue;
        }

        if (ticket.getTicketStatus() == null) {
          ticketStatus = -1;
          break;
        }

        if (ticket.getTicketStatus() == 1
                || ticket.getTicketStatus() == 2
                || ticket.getTicketStatus() == 3
                || ticket.getTicketStatus() == 4
                || ticket.getTicketStatus() == 128) {
          ticketStatus = 1;
        } else {
          ticketStatus = -1;
          break;
        }
      }

      if (ticketStatus >= 0) {
        psg.setTicketStatus(ticketStatus);
      }
    }

  }

  public List<ApiPriceDto> getPrices() {
    if (prices == null) {
      prices = new ArrayList<>();
    }
    return prices;
  }

  public void setPrices(List<ApiPriceDto> prices) {
    this.prices = prices;
  }


  public String getLinkman() {
    return linkman;
  }

  public void setLinkman(String linkman) {
    this.linkman = linkman;
  }

  public String getLinkPhone() {
    return linkPhone;
  }

  public void setLinkPhone(String linkPhone) {
    this.linkPhone = linkPhone;
  }

  public int getIntlTicket() {
    return intlTicket;
  }

  public void setIntlTicket(int intlTicket) {
    this.intlTicket = intlTicket;
  }


  public int getItineraryType() {
    return itineraryType;
  }

  public void setItineraryType(int itineraryType) {
    this.itineraryType = itineraryType;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getRemark() {
    return remark;
  }

  public void setRemark(String remark) {
    this.remark = remark;
  }

  public String getPolicyCode() {
    return policyCode;
  }

  public void setPolicyCode(String policyCode) {
    this.policyCode = policyCode;
  }


  public double getTotalAmount() {
    return totalAmount;
  }

  public void setTotalAmount(double totalAmount) {
    this.totalAmount = totalAmount;
  }


  public String getOperator() {
    return operator;
  }

  public void setOperator(String operator) {
    this.operator = operator;
  }


  public String getPnrNo() {
    return pnrNo;
  }

  public void setPnrNo(String pnrNo) {
    this.pnrNo = pnrNo;
  }

  public String getPnrDetail() {
    return pnrDetail;
  }

  public void setPnrDetail(String pnrDetail) {
    this.pnrDetail = pnrDetail;
  }


  public String getPayRemark() {
    return payRemark;
  }

  public void setPayRemark(String payRemark) {
    this.payRemark = payRemark;
  }


  public int getRouteType() {
    return routeType;
  }

  public void setRouteType(int routeType) {
    this.routeType = routeType;
  }


  public Double getSubTotal() {
    return subTotal;
  }

  public void setSubTotal(Double subTotal) {
    this.subTotal = subTotal;
  }

  public Date getCreateDate() {
    return createDate;
  }

  public void setCreateDate(Date createDate) {
    this.createDate = createDate;
  }

  public int getPriceCheckedStatus() {
    return priceCheckedStatus;
  }

  public void setPriceCheckedStatus(int priceCheckedStatus) {
    this.priceCheckedStatus = priceCheckedStatus;
  }

  public Date getPriceCheckedTime() {
    return priceCheckedTime;
  }

  public void setPriceCheckedTime(Date priceCheckedTime) {
    this.priceCheckedTime = priceCheckedTime;
  }


  @Override
  public String getSpecifiedApprover() {
    return specifiedApprover;
  }

  @Override
  public void setSpecifiedApprover(String specifiedApprover) {
    this.specifiedApprover = specifiedApprover;
  }

  @Override
  public Integer getApprovalStatus() {
    return approvalStatus;
  }

  @Override
  public void setApprovalStatus(Integer approvalStatus) {
    this.approvalStatus = approvalStatus;
  }

  @Override
  public String getApprovalDenyReason() {
    return approvalDenyReason;
  }

  @Override
  public void setApprovalDenyReason(String approvalDenyReason) {
    this.approvalDenyReason = approvalDenyReason;
  }

  @Override
  public Integer getViolationStatus() {
    return violationStatus;
  }

  @Override
  public void setViolationStatus(Integer violationStatus) {
    this.violationStatus = violationStatus;
  }

  @Override
  public String getViolationReason() {
    return violationReason;
  }

  @Override
  public void setViolationReason(String violationReason) {
    this.violationReason = violationReason;
  }
}
